package com.csw.mysqldate.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
import java.util.Date;

@RestController
@Slf4j
@RequestMapping("file")
public class FileController {
    private static final String WAV = "wav";
    private static final String USER_AGENT = "User-Agent";
    private static final String MP3 = "mp3";
    private static final String OGG = "ogg";
    private static final String CONTENT_DISPOSITION = "Content-Disposition";
    private static final String CONTENT_LENGTH = "Content-Length";
    private static final String CONTENT_RANGE = "Content-Range";
    private static final String BYTES = "bytes";

    public void download(String path, HttpServletRequest request, HttpServletResponse response) throws Exception {
        //path解密之后获取文佳所在的路径
        File file = new File(path);
        if (file.exists()) {
            String prefix = path.substring(path.lastIndexOf(".") + 1);
            String oldFileName = file.getName();
            String fileName;
            if (request.getHeader(USER_AGENT).contains("MSIE")
                    || request.getHeader(USER_AGENT).contains("Trident")) {
                fileName = java.net.URLEncoder.encode(oldFileName, String.valueOf(StandardCharsets.UTF_8));
            } else if (request.getHeader(USER_AGENT).contains("iPhone")
                    || request.getHeader(USER_AGENT).contains("iPod")
                    || request.getHeader(USER_AGENT).contains("iPad")) {
                fileName = new String(oldFileName.getBytes("GB2312"), StandardCharsets.ISO_8859_1);
            } else {
                fileName = new String(oldFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            }
            response.reset();
            String type = this.type(prefix);
            response.setContentType(type);
            if (MP3.equals(prefix) || WAV.equals(prefix) || OGG.equals(prefix)) {
                response.addHeader(CONTENT_DISPOSITION, "inline;filename=" + fileName);
                response.setHeader("Accept-Ranges", BYTES);
                response.setHeader("ETag", fileName);
                response.setHeader("Last-Modified", new Date().toString());
                String range = request.getHeader("Range");
                long contentLength = file.length();
                long requestStart = 0, requestEnd = 0;
                long length;
                if (range == null) {
                    response.setHeader(CONTENT_LENGTH, contentLength + "");
                    length = contentLength;
                } else {
                    //以后的多次以断点续传的方式返回视频数据
                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                    String bytes = range.replaceAll("bytes=", "");
                    String[] ary = bytes.split("-");
                    requestStart = Long.parseLong(ary[0]);
                    if (ary.length == 2) {
                        requestEnd = Long.parseLong(ary[1]);
                    }
                    if (requestEnd > 0) {
                        length = requestEnd - requestStart + 1;
                        response.setHeader(CONTENT_LENGTH, length + "");
                        response.setHeader(CONTENT_RANGE, BYTES + requestStart + "-" + requestEnd + "/" + contentLength);
                    } else {
                        length = contentLength - requestStart;
                        response.setHeader(CONTENT_LENGTH, length + "");
                        response.setHeader(CONTENT_RANGE, BYTES + requestStart + "-" + (contentLength - 1) + "/" + contentLength);
                    }
                }
                //只读模式
                try (RandomAccessFile randomFile = new RandomAccessFile(file, "r")) {
                    OutputStream out = response.getOutputStream();
                    //设置下载起始位置
                    if (requestStart > 0) {
                        randomFile.seek(requestStart);
                    }
                    //缓冲区大小
                    long limit = length;
                    //缓冲大小
                    int bufferSize = (int) (limit > 8192 ? 8192 : limit);
                    byte[] buffer = new byte[bufferSize];
                    int num;
                    while (limit > 0 && (num = randomFile.read(buffer)) != -1) {
                        out.write(buffer, 0, num);
                        limit -= num;
                        if (limit < bufferSize) {
                            buffer = new byte[(int) limit];
                        }
                    }
                    response.flushBuffer();
                } catch (Exception e) {
                    log.info("数据被暂停或中断,{}", e);
                }
            } else {
                //设置response参数，可以打开下载界面
                if ("pdf".equals(prefix)) {
                    fileName = java.net.URLEncoder.encode(oldFileName, String.valueOf(StandardCharsets.UTF_8));
                    response.addHeader(CONTENT_DISPOSITION, "inline;filename=" + fileName);
                    response.setContentType("application/pdf;charset=" + StandardCharsets.UTF_8);
                } else {
                    response.setHeader(CONTENT_DISPOSITION, "attachment;filename=" + fileName);
                }
                response.addHeader(CONTENT_LENGTH, String.valueOf(file.length()));
                try (InputStream bis = new BufferedInputStream(new FileInputStream(path))) {
                    try (OutputStream bos = new BufferedOutputStream(response.getOutputStream())) {
                        byte[] buffer = new byte[bis.available()];
                        bis.read(buffer);
                        bos.write(buffer);
                        bos.flush();
                        response.flushBuffer();
                    }
                }
            }

        }
    }

    public String type(String prefix) {
        String type;
        if ("pdf".equalsIgnoreCase(prefix)) {
            type = "application/pdf";
        } else if ("doc".equalsIgnoreCase(prefix)) {
            type = "application/msword";
        } else if ("docx".equalsIgnoreCase(prefix)) {
            type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        } else if ("pptx".equalsIgnoreCase(prefix)) {
            type = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
        } else if ("ppt".equalsIgnoreCase(prefix)) {
            type = "application/vnd.ms-powerpoint";
        } else if ("xlsx".equalsIgnoreCase(prefix)) {
            type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        } else if ("xls".equalsIgnoreCase(prefix)) {
            type = "application/vnd.ms-excel";
        } else if (MP3.equalsIgnoreCase(prefix)) {
            type = "application/mpeg";
        } else if (WAV.equalsIgnoreCase(prefix)) {
            type = "application/wav";
        } else if (OGG.equalsIgnoreCase(prefix)) {
            type = "application/ogg";
        } else {
            type = "application/octet-stream";
        }
        return type;
    }
}
